-- 3d vectors
local metatable={ __index={}}

function metatable.__add(a,b)            return setmetatable({a[1]+b[1], a[2]+b[2], a[3]+b[3]},metatable) end
function metatable.__sub(a,b)            return setmetatable({a[1]-b[1], a[2]-b[2], a[3]-b[3]},metatable) end
function metatable.__div(a,s)            return setmetatable({a[1]/s, a[2]/s, a[3]/s},metatable) end
function metatable.__unm(a)              return setmetatable({-a[1], -a[2], -a[3]},metatable) end
function metatable.__tostring(a)         return "{"..a[1]..", "..a[2]..", "..a[3].."}" end
function metatable.__mul(a,b)    
  if type(b)=="number" then return setmetatable({a[1]*b, a[2]*b, a[3]*b},metatable) 
  elseif type(a)=="number" then return setmetatable({a*b[1], a*b[2], a*b[3]},metatable) end 
end

Vector=setmetatable(metatable,{__call=function(self,arg) return setmetatable(arg,self) end })
vector={}
function vector.dot(a,b) return a[1]*b[1]+a[2]*b[2]+a[3]*b[3] end
function vector.cross(a,b) return setmetatable({a[2]*b[3]-a[3]*b[2], a[3]*b[1]-a[1]*b[3], a[1]*b[2]-a[2]*b[1]},metatable) end
function vector.abs(a) return math.sqrt(a[1]*a[1]+a[2]*a[2]+a[3]*a[3]) end
function vector.unit(a) local s=1/math.sqrt(a[1]*a[1]+a[2]*a[2]+a[3]*a[3]) return setmetatable({a[1]*s,a[2]*s,a[3]*s},metatable) end
function vector.project(a,b) local s=(a[1]*b[1]+a[2]*b[2]+a[3]*b[3])/(b[1]*b[1]+b[2]*b[2]+b[3]*b[3]) return setmetatable({b[1]*s,b[2]*s,b[3]*s},metatable) end
function vector.rotate(v,k,w) return v*math.cos(w) + vector.cross(k,v)*math.sin(w) + k*vector.dot(k,v)*(1-math.cos(w)) end